//
//  MKSystemPhotosViewController.swift
//  MKImageBrowser3
//
//  Created by 劢克科技 on 2019/5/10.
//  Copyright © 2019 meckey. All rights reserved.
//  展示系统相册的CollectionView

import UIKit
import Photos

protocol MKSystemPhotosViewControllerDelegate {
    func handleSelected(images: [IndexPath: UIImage], orderImages: [[IndexPath: UIImage]])
}

class MKSystemPhotosViewController: UIViewController {

    var delegate: MKSystemPhotosViewControllerDelegate?
    let systemCellIdentifier = "systemCellIdentifier"
    let systemVideoCellId = "systemVideoCellId"
    
    override func viewDidLoad() {
        super.viewDidLoad()

        setupUI()
        
        if fetchResult == nil {
            let allPhotoOptions = PHFetchOptions()
            allPhotoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
            fetchResult = PHAsset.fetchAssets(with: allPhotoOptions)
        }
        
        PHPhotoLibrary.shared().register(self)
    }
    
    deinit {
        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }
    
    //MARK: - Setter
    
    var selectedIndexPath = [IndexPath]()                   // 缓存选中的Index
    fileprivate var thumbImages = [IndexPath: UIImage]()    // 缓存缩略图
    fileprivate var images = [IndexPath: UIImage]()         // 缓存大图
    fileprivate var orderImages = [[IndexPath: UIImage]]()
    
    // 初始化选中的照片
    func setSelectedImages(images: [IndexPath: UIImage], orderImages: [[IndexPath: UIImage]]) {
        self.images = images
        self.orderImages = orderImages
        for item in images {
            selectedIndexPath.append(item.key)
        }
    }
    
    //MARK: - Getter
    
    fileprivate var fetchResult: PHFetchResult<PHAsset>!
    fileprivate let imageManager = PHImageManager()
    
    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let itemWH = (UIScreen.main.bounds.width - 9) / 4
        layout.itemSize = CGSize(width: itemWH, height: itemWH)
        layout.minimumLineSpacing = 3
        layout.minimumInteritemSpacing = 3
        let collectionV = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionV.register(MKSystemPhotoCollectionViewCell.self, forCellWithReuseIdentifier: self.systemCellIdentifier)
        collectionV.register(MKSystemVieoCollectionViewCell.self, forCellWithReuseIdentifier: self.systemVideoCellId)
        collectionV.delegate = self
        collectionV.dataSource = self
        collectionV.alwaysBounceVertical = true
        collectionV.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        return collectionV
    }()
    
    lazy var toolBar: UIView = {
        let view = UIView()
        view.backgroundColor = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)
        return view
    }()
    
    lazy var preButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("预览", for: .normal)
        button.setTitleColor(#colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), for: .normal)
        button.backgroundColor = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
        button.addTarget(self, action: #selector(handlePreclick), for: .touchUpInside)
        return button
    }()
    
    //MARK: - Events
    
    // 点击预览按钮，弹出MKImageBrowser插件
    @objc fileprivate func handlePreclick() {
        if !hasSelectedPhoto() {
            return
        }
        
        let controller = MKSystemPreviewViewController()
        controller.setImages(images: self.orderImages)
        navigationController?.pushViewController(controller, animated: true)
    }
    
    
    /// 判断是否有选中的图片
    ///
    /// - Returns: Bool
    fileprivate func hasSelectedPhoto() -> Bool {
        return selectedIndexPath.count != 0
    }
    
    
    /// 根据index，获取高清的image
    ///
    /// - Parameter index: indexPath
    /// - Returns: Hd image
    fileprivate func getHdPicture(index: IndexPath) -> UIImage {
        var resImage = UIImage()
        let options = PHImageRequestOptions()
        let asset = self.fetchResult.object(at: index.item)
        options.isSynchronous = true
        options.resizeMode = .fast
        let identifier = asset.localIdentifier
        let imageWidth = Int(UIScreen.main.bounds.width * 3)
        let imageHeight = asset.pixelHeight * imageWidth / asset.pixelWidth
        self.imageManager.requestImage(for: asset, targetSize: CGSize(width: imageWidth, height: imageHeight), contentMode: .default, options: options, resultHandler: { (image, _) in
            if asset.localIdentifier == identifier {
                resImage = image!
            }
        })
        return resImage
    }
}

//MARK: - < Observer Photo Change >

extension MKSystemPhotosViewController: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        DispatchQueue.main.async {
            let allPhotoOptions = PHFetchOptions()
            allPhotoOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
            self.fetchResult = PHAsset.fetchAssets(with: allPhotoOptions)
            self.collectionView.reloadData()
        }
    }
}

//MARK: - < CollectionView Delegate / DataSource >

extension MKSystemPhotosViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return fetchResult.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let asset = fetchResult.object(at: indexPath.item)
        
        if asset.mediaType == .image {
            return getImageCell(collectionView: collectionView, indexPath: indexPath)
        } else {
            return getVideoCell(collectionView: collectionView, indexPath: indexPath)
        }
    }
    
    // 获取图片Cell
    fileprivate func getImageCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell {
        let asset = fetchResult.object(at: indexPath.item)
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: systemCellIdentifier, for: indexPath) as! MKSystemPhotoCollectionViewCell
        
        if thumbImages[indexPath] != nil {
            cell.image = self.thumbImages[indexPath]
        } else {
            
            let identifier = asset.localIdentifier
            imageManager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: nil) { (image, _) in
                if asset.localIdentifier == identifier {
                    cell.image = image
                    self.thumbImages[indexPath] = image
                }
            }
        }
        
        cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
        
        if selectedIndexPath.contains(indexPath) {
            cell.setStatus(selected: true)
        } else {
            cell.setStatus(selected: false)
        }
        
        return cell
    }
    
    // 获取视频Cell
    fileprivate func getVideoCell(collectionView: UICollectionView, indexPath: IndexPath) -> UICollectionViewCell {
        let asset = fetchResult.object(at: indexPath.item)
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: systemVideoCellId, for: indexPath) as! MKSystemVieoCollectionViewCell
        
        if thumbImages[indexPath] != nil {
            cell.image = self.thumbImages[indexPath]
        } else {
            
            let identifier = asset.localIdentifier
            imageManager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: nil) { (image, _) in
                if asset.localIdentifier == identifier {
                    cell.image = image
                    self.thumbImages[indexPath] = image
                }
            }
        }
        
        cell.backgroundColor = #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1)
        
        if selectedIndexPath.contains(indexPath) {
            cell.setStatus(selected: true)
        } else {
            cell.setStatus(selected: false)
        }
        
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let asset = fetchResult.object(at: indexPath.item)
        if asset.mediaType == .image {
            // 选中图片
            let cell = collectionView.cellForItem(at: indexPath) as! MKSystemPhotoCollectionViewCell
            if cell.status == .selected {
                // 取消选中
                cell.setStatus(selected: false)
                selectedIndexPath = selectedIndexPath.filter({ (index) -> Bool in
                    return index != indexPath
                })
                self.images.removeValue(forKey: indexPath)
                self.orderImages = self.orderImages.filter({ (imageDict) -> Bool in
                    return imageDict.keys.first != indexPath
                })
            } else {
                // 选中一张
                cell.setStatus(selected: true)
                selectedIndexPath.append(indexPath)
                let hdImage = getHdPicture(index: indexPath)
                self.images[indexPath] = hdImage
                self.orderImages.append([indexPath: hdImage])
            }
        } else {
            // 选中视频
            let cell = collectionView.cellForItem(at: indexPath) as! MKSystemVieoCollectionViewCell
            if cell.status == .selected {
                // 取消选中
                cell.setStatus(selected: false)
                selectedIndexPath = selectedIndexPath.filter({ (index) -> Bool in
                    return index != indexPath
                })
                self.images.removeValue(forKey: indexPath)
                self.orderImages = self.orderImages.filter({ (imageDict) -> Bool in
                    return imageDict.keys.first != indexPath
                })
            } else {
                // 选中一张
                cell.setStatus(selected: true)
                selectedIndexPath.append(indexPath)
                let hdImage = getHdPicture(index: indexPath)
                self.images[indexPath] = hdImage
                self.orderImages.append([indexPath: hdImage])
            }
        }
    }
}

//MARK: - setupUI

extension MKSystemPhotosViewController {
    fileprivate func setupUI() {
        title = "系统相册"

        let button = UIBarButtonItem(image: #imageLiteral(resourceName: "back blue"), style: .done, target: self, action: #selector(close))
        button.imageInsets = UIEdgeInsets(top: 0, left: -10, bottom: 0, right: 0)
        let submitButton = UIBarButtonItem(title: "确认", style: .plain, target: self, action: #selector(submit))
        
        self.navigationItem.leftBarButtonItem = button
        self.navigationItem.rightBarButtonItem = submitButton
        
        view.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        addSubs()
        layoutSubs()
    }
    
    @objc fileprivate func submit() {
        dismiss(animated: true) {
            // 将照片读取出来
            self.delegate?.handleSelected(images: self.images, orderImages: self.orderImages)
        }
    }
    
    @objc fileprivate func close() {
        dismiss(animated: true, completion: nil)
    }
    
    fileprivate func addSubs() {
        view.addSubview(collectionView)
        view.addSubview(toolBar)
        toolBar.addSubview(preButton)
    }
    
    fileprivate func layoutSubs() {
        collectionView.snp.makeConstraints { (make) in
            make.left.equalTo(view.snp_left)
            make.right.equalTo(view.snp_right)
            make.top.equalTo(view.snp_top)
            make.bottom.equalTo(view.snp_bottom).offset(-50)
        }
        
        toolBar.snp.makeConstraints { (make) in
            make.left.equalTo(view.snp_left)
            make.right.equalTo(view.snp_right)
            make.height.equalTo(50)
            make.bottom.equalTo(view.snp_bottom)
        }
        
        preButton.snp.makeConstraints { (make) in
            make.width.equalTo(80)
            make.height.equalTo(50)
            make.right.equalTo(toolBar.snp_right)
            make.top.equalTo(toolBar.snp_top)
        }
    }
}
